package com.yootk.main;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

/**
 * SpEL表达式
 */
public class Demo03_Expression {
    private static final Logger LOGGER = LoggerFactory.getLogger(Demo03_Expression.class);

    public static void main(String[] args) {
//        test1();
//        test2();
//        test3();
//        test4();
//        test5();
//        test6();
        test7();
    }

    /**
     * SpEL字面表达式
     */
    public static void test1() {
        LOGGER.info("【字面表达式】：{}", spel("'Muyan ' + \"Yootk\""));
        LOGGER.info("【字面表达式】：{}", spel("#{ 'Muyan ' + \"Yootk\" }"));
        LOGGER.info("【字面表达式】：{}，对象类型：{}", spel("#{ 1 }"), spel("#{ 1 }").getClass());
        LOGGER.info("【字面表达式】：{}，对象类型：{}", spel("#{ 1.1 }"), spel("#{ 1.1 }").getClass());
        LOGGER.info("【字面表达式】：{}，对象类型：{}", spel("#{ 1.1E10 }"), spel("#{ 1.1E10 }").getClass());
        LOGGER.info("【字面表达式】：{}，对象类型：{}", spel("#{ true }"), spel("#{ true }").getClass());
    }

    /**
     * SpEL数学表达式
     */
    public static void test2() {
        LOGGER.info("【数学表达式】：{}，数据类型：{}", spel("#{ 1 + 2 - 3 * 4 / 5 }"), spel("#{ 1 + 2 - 3 * 4 / 5 }").getClass());
        LOGGER.info("【数学表达式】：{}，数据类型：{}", spel("#{ 10 % 3 }"), spel("#{ 10 % 3 }").getClass());
        LOGGER.info("【数学表达式】：{}，数据类型：{}", spel("#{ 10 mod 3 }"), spel("#{ 10 mod 3 }").getClass());
        LOGGER.info("【数学表达式】：{}，数据类型：{}", spel("#{ 10 div 3 }"), spel("#{ 10 div 3 }").getClass());
        LOGGER.info("【数学表达式】：{}，数据类型：{}", spel("#{ 10 ^ 3 }"), spel("#{ 10 ^ 3 }").getClass());
    }

    /**
     * SpEL关系表达式
     */
    public static void test3() {
        LOGGER.info("【关系表达式】：{}", spel("#{ 30 != 20 }"));
        LOGGER.info("【关系表达式】：{}", spel("#{ 30 NE 20 }"));
        LOGGER.info("【关系表达式】：{}", spel("#{ 'muyan' > 'MuYan' }"));
        LOGGER.info("【关系表达式】：{}", spel("#{ 10 + 20 eq 30 }"));
    }

    /**
     * SpEL逻辑表达式
     */
    public static void test4() {
        LOGGER.info("【逻辑表达式】：{}", spel("#{ 30 != 20 || 10 EQ 10 }"));
        LOGGER.info("【逻辑表达式】：{}", spel("#{ 'muyan' > 'MuYan' AND 'Yootk' LT 'yootk' }"));
        LOGGER.info("【逻辑表达式】：{}", spel("#{ 10 BETWEEN {0, 100} AND 1 == 1 }"));
        LOGGER.info("【逻辑表达式】：{}", spel("#{ 'y' BETWEEN {'a', 'z'} }"));
    }

    /**
     * SpEL三目运算符
     */
    public static void test5() {
        // 基本三目运算
        LOGGER.info("【基本三目运算】：{}", spel("#{ 'muyan' != null ? 'www.yootk.com' : 'www.jixianit.com' }"));
        // 在Spring之中考虑到null的影响，所以null也是可以直接进行判断逻辑处理的
        LOGGER.info("【基本三目运算】：{}", spel("#{ null == null ? 'www.yootk.com' : 'www.jixianit.com' }"));
        LOGGER.info("【基本三目运算】：{}", spel("#{ true ? 'www.yootk.com' : 'www.jixianit.com' }"));
//        LOGGER.info("【基本三目运算】：{}", spel("#{ null ? 'www.yootk.com' : 'www.jixianit.com' }"));
        // 如果此时的内容是null，则就认为表达式的判断结果为false，那么获取三目之中false的内容
        LOGGER.info("【SpEL三目拓展】：{}", spel("#{ null ?: 'www.jixianit.com' }"));
        // 如果不是null，就直接使用表达式的内容进行返回
        LOGGER.info("【SpEL三目拓展】：{}", spel("#{ 'yootk' ?: 'www.jixianit.com' }"));
    }

    /**
     * SpEL字符串处理表达式
     */
    public static void test6() {
        LOGGER.info("【字符串处理】：{}", spel("#{ 'www.yootk.com'[8] }"));
        LOGGER.info("【字符串处理】：{}", spel("#{ 'www.yootk.com'.substring(4, 'www.yootk.com'.length()) }"));
        LOGGER.info("【字符串处理】：{}", spel("#{ 'www.yootk.com'.replaceAll('yootk', 'jixianit') }"));
        // 正则匹配
        LOGGER.info("【字符串处理】：{}", spel("#{ 'www.yootk.com'.matches('\\w+\\.\\w+\\.\\w+') }"));
        LOGGER.info("【字符串处理】：{}", spel("#{ 'www.yootk.com' matches '\\w+\\.\\w+\\.\\w+' }"));
    }

    /**
     * Class表达式
     */
    public static void test7() {
        LOGGER.info("【Class表达式】：{}", spel("#{ T(java.lang.String) }"));
        LOGGER.info("【Class表达式】：{}", spel("#{ T(java.util.Date) }"));
        // 调用Integer类中方法和常量
        LOGGER.info("【Class表达式】：{}", spel("#{ T(java.lang.Integer).MAX_VALUE }"));
        LOGGER.info("【Class表达式】：{}", spel("#{ T(java.lang.Integer).parseInt('919') }"));
        // 使用自定义类实现对象实例化
        LOGGER.info("【Class表达式】：{}", spel("#{ T(com.yootk.vo.Book) }"));
        LOGGER.info("【Class表达式】：{}", spel("#{ new com.yootk.vo.Book('Spring开发实战', 79.8) }"));
    }

    /**
     * 实现SpEL处理
     */
    private static Object spel(String content) {
        ExpressionParser parser = new SpelExpressionParser();   // 定义SpEL解析器
        Expression exp = parser.parseExpression(content, ParserContext.TEMPLATE_EXPRESSION);    // 表达式解析
        EvaluationContext context = new StandardEvaluationContext();    // 表达式上下文配置
        return exp.getValue(context);
    }
}
